package conductores;

import java.util.ArrayList;

public class Conductor implements Cloneable, Comparable<Conductor>{

	public int identificador;
	public int distanciaTotal;
	ArrayList<Integer> ruta = new ArrayList<Integer>();

	public Conductor(int identificador) {
		this.identificador = identificador;
		calculaDistancia();
	}
	
	public int getDistanciaTotal() {
		return distanciaTotal;
	}

	public ArrayList<Integer> getRuta() {
		ArrayList<Integer> newRuta = this.ruta;
		return newRuta;
	}

	public int numOcupantes(int posicion) {
		int numOcupantes = 0;
		
		boolean zero = false;

		for (int i = 0; i < posicion; i++) {
			if (ruta.get(i) > 0) {
				numOcupantes++;				
			} else {
				if(this.ruta.get(i) == 0) {
					if(!zero) { 
						numOcupantes++;
						zero = true;
					} else {
						numOcupantes--;
					}
				} else {
					numOcupantes--;
				}
			}
		}
		
		return numOcupantes;
	}
	
    public int CalculaDistanciaConductorUsuario(int usuario){    	
    	Point start_cond=Context.coordenadas[Context.usuarios[this.identificador].origen];
    	Point start_user=Context.coordenadas[Context.usuarios[usuario].origen];
    	return start_user.distancia(start_cond,start_user);
    }
	
    public int CalculaDistanciaRutafinalUsuario(int usuario){
    	int distancia=0;
    	Point fin_cond;
    	if(ruta.size()==0){
    		fin_cond=Context.coordenadas[Context.usuarios[identificador].origen];
    		}
    	else {
    		fin_cond=Context.coordenadas[Context.usuarios[ruta.get(ruta.size()-2)].destino];
    	}
    	Point start_user=Context.coordenadas[Context.usuarios[usuario].origen];
    	distancia=start_user.distancia(fin_cond,start_user);
    	
    	
    	return distancia;
    }
    
	public int calculaDistancia() {
		this.distanciaTotal = calculaDistancia(this.ruta);
		return this.distanciaTotal;
	}

	public int calculaDistancia(ArrayList<Integer> rutaTemp) {

		int distancia = 0;

		Usuario[] usuarios = Context.getInstance().getUsuarios();
		Point[] coordenadas = Context.coordenadas;

		Point start = coordenadas[usuarios[this.identificador].origen];
		Point end;
		boolean cero = false;

		for (int i = 0; i < rutaTemp.size(); i++) {
			int userID = rutaTemp.get(i);

			if (userID > 0) {
				end = coordenadas[usuarios[userID].origen];
			} else if (userID == 0) {
				if (!cero) {
					end = coordenadas[usuarios[userID].origen];
					cero = true;
				} else {
					end = coordenadas[usuarios[userID].destino];
				}
			} else {
				end = coordenadas[usuarios[-userID].destino];
			}
			
			distancia += start.distancia(end);
			start = end;
		}
		
		end = coordenadas[usuarios[this.identificador].destino];

		distancia += start.distancia(end);
		
		return distancia;
	}
	
	public Conductor clone() {		   	
		return this.clone(getClonedRuta(), distanciaTotal);		
	}
	
	public Conductor clone(ArrayList<Integer> newruta) {
		return this.clone(newruta, calculaDistancia(newruta));
	}
	
	public Conductor clone(ArrayList<Integer> newruta, int distanciaTotal) {
		Conductor clone = new Conductor(identificador);
		clone.ruta = newruta;
		clone.distanciaTotal = distanciaTotal;
		return clone;
		
	}
	
	public ArrayList<Integer> getClonedRuta() {
		
		ArrayList<Integer> clone = new ArrayList<Integer>();
		
		for(Integer dest : getRuta()) {
    		clone.add(dest);
    	}
		
		return clone;
		
	}
 
	public boolean equals(Conductor cond) {
		return (identificador == cond.identificador);
	}
	
	public void Move(Conductor cdesti, int user) {
		this.removeUser(user);		
		cdesti.queueUser(user);
    }
	
	public void queueUser(int user) {
		queueUser(user, getRuta());
	}
	
	public void queueUser(int user, ArrayList<Integer> ruta) {		
		ruta.add((Integer)user);
		ruta.add((Integer)(-user));
		calculaDistancia();
	}
	
	public void addUser(int user, int pos) {
		addUser(user, pos, pos);
	}
	
	public void addUser(int user, int posO, int posD) {		
		ruta.add(posD, (Integer)(-user));
		ruta.add(posO, (Integer)user);
		calculaDistancia();
	}
	
	public void removeUser(int user) {
		removeUser(user, getRuta());
	}
	
	public void removeUser(int user, ArrayList<Integer> ruta) {		
		ruta.remove((Integer)user);
		ruta.remove((Integer)(-user));
		calculaDistancia();
	}
	
	public boolean ValidarRuta() {
		
		int numOcupantes = 0;		
		boolean zero = false;
		
		if(getDistanciaTotal() > Context.MAXDIST) { return false; }

		for (int i = 0; i < getRuta().size(); i++) {
			if (ruta.get(i) > 0) {
				numOcupantes++;				
			} else {
				if(this.ruta.get(i) == 0) {
					if(!zero) { 
						numOcupantes++;
						zero = true;
					} else {
						numOcupantes--;
					}
				} else {
					numOcupantes--;
				}
			}
			
			if(numOcupantes > 2) return false;
		}
		
		return true;
	}
	
	public boolean transportaAlgunUsuari() {
		return getRuta().isEmpty();
	}

	@Override
	public int compareTo(Conductor c) {
		if(this.distanciaTotal > c.distanciaTotal) {           
            return 1;
        }
        return -1;
	}
}
